package archforce.atp.x.ssh.jsch;

import archforce.atp.x.ssh.entity.JumpConfig;
import archforce.atp.x.ssh.entity.JumpMappingConfig;
import archforce.atp.x.ssh.entity.PortMappingEntity;
import archforce.atp.x.ssh.tool.JumpMappingCmdTool;
import archforce.atp.x.ssh.tool.PersistenceConfigTool;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author wx
 * @version 1.0
 * @date 2022/4/28 13:50
 */
public class JschDockerService {

    public static Session[] connectAndMapping(JumpMappingConfig jumpMappingConfig){
        List<JumpConfig.ServerEntity> jumpHost = jumpMappingConfig.getJumpConfig().getJumpHost();
        JSch jSch = new JSch();
        JumpConfig.ServerEntity master = jumpHost.get(0);
        Session[] sessions = new Session[jumpHost.size() + 1];
        Session session = null;
        try{
            sessions[0] = session = jSch.getSession(master.getUser(), master.getHostIP(), master.getPort());
            sessions[0].setConfig("StrictHostKeyChecking", "no");
            sessions[0].setPassword(master.getPassword());
            sessions[0].connect();
        } catch (JSchException e) {
            e.printStackTrace();
            session.disconnect();
        }finally {
            System.out.println("master(" + master + ")is connected:" + session.isConnected());
        }
        jumpHost.add(jumpMappingConfig.getJumpConfig().getDockerCMasterServer());
        for (int i = 0; i < jumpHost.size(); i++) {
            JumpConfig.ServerEntity host = jumpHost.get(i);
            Integer assingedPort = null;
            try{
                assingedPort = session.setPortForwardingL(0, host.getHostIP(), host.getPort());
                sessions[i] = session = jSch.getSession(host.getUser(), "127.0.0.1", assingedPort);
                sessions[i].setConfig("StrictHostKeyChecking", "no");
                sessions[i].setPassword(host.getPassword());
                sessions[i].connect();
            } catch (JSchException e) {
                e.printStackTrace();
                System.out.println(host + "链接失败");
                if(session != null){
                    session.disconnect();
                }
            }finally {
                System.out.println("host(" + host + ")is connected:" + session.isConnected() + "----assingedPort:" + assingedPort);
            }
        }
        Session finalSession = session;
        jumpMappingConfig.getMappingPortConfig().stream().forEach(mapping ->{
            try {
                finalSession.setPortForwardingL(mapping.getLocalhost(), mapping.getLocalPort(), mapping.getRemoteHost(), mapping.getRemotePort());
                System.out.println("mapping:" + mapping);
            } catch (JSchException e) {
                e.printStackTrace();
            }
        });
        return sessions;
    }

    public static void disConnected(Session[] sessions){
        Stream.of(sessions).forEach(Session::disconnect);
    }

    public static JumpMappingConfig prepareData(){
        List<JumpConfig.ServerEntity> jumpHostList = new ArrayList<>();
        jumpHostList.add(new JumpConfig.ServerEntity("10.129.1.24", "archforce", "archforce"));
        jumpHostList.add(new JumpConfig.ServerEntity("10.120.0.138", "root", "123456"));
        JumpConfig jumpConfig = new JumpConfig(jumpHostList);
        jumpConfig.setDockerCMasterServer("192.2.110.4", "archforce", "archforce");

        List<PortMappingEntity> mappingConfigs = new ArrayList<>();
        mappingConfigs.add(new PortMappingEntity("192.2.110.4", 8090, "192.2.110.4", 8090));

        JumpMappingConfig data = new JumpMappingConfig(jumpConfig, mappingConfigs);
        return data;
    }

    public static void main(String[] args) {
        JumpMappingConfig jumpMappingConfig = prepareData();
        System.out.println("SSH Command Line:" + JumpMappingCmdTool.buildSSHWholeCmd(jumpMappingConfig));
        Session[] sessions = connectAndMapping(jumpMappingConfig);
        try{
            PersistenceConfigTool.persistenceJumpMappingData(jumpMappingConfig);
            PersistenceConfigTool.load();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        Stream.of(sessions).forEach(Session::disconnect);
    }
}
